home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / ASTFuncCall.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  8.5 KB  |  243 lines  |  [TEXT/KAHL]

  1. /* ASTFuncCall.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "ASTFuncCall.h"
  31. #include "ASTExpressionList.h"
  32. #include "TrashTracker.h"
  33. #include "Memory.h"
  34. #include "ASTExpression.h"
  35. #include "SymbolTableEntry.h"
  36. #include "SymbolList.h"
  37. #include "PromotableTypeCheck.h"
  38. #include "ASTOperand.h"
  39.  
  40.  
  41. struct ASTFuncCallRec
  42.     {
  43.         ASTExprListRec*            ArgumentList;
  44.         ASTExpressionRec*        FunctionGenerator;
  45.         long                                LineNumber;
  46.     };
  47.  
  48.  
  49. /* create a new function call node.  the argument list can be NIL if there are */
  50. /* no arguments. */
  51. ASTFuncCallRec*            NewFunctionCall(struct ASTExprListRec* ArgumentList,
  52.                                             struct ASTExpressionRec* FunctionGeneratorExpression,
  53.                                             struct TrashTrackRec* TrashTracker, long LineNumber)
  54.     {
  55.         ASTFuncCallRec*        FuncCall;
  56.  
  57.         CheckPtrExistence(FunctionGeneratorExpression);
  58.         if (ArgumentList != NIL)
  59.             {
  60.                 CheckPtrExistence(ArgumentList);
  61.             }
  62.         CheckPtrExistence(TrashTracker);
  63.         FuncCall = (ASTFuncCallRec*)AllocTrackedBlock(sizeof(ASTFuncCallRec),TrashTracker);
  64.         if (FuncCall == NIL)
  65.             {
  66.                 return NIL;
  67.             }
  68.         SetTag(FuncCall,"ASTFuncCallRec");
  69.  
  70.         FuncCall->LineNumber = LineNumber;
  71.         FuncCall->ArgumentList = ArgumentList;
  72.         FuncCall->FunctionGenerator = FunctionGeneratorExpression;
  73.  
  74.         return FuncCall;
  75.     }
  76.  
  77.  
  78. /* type check the function call node.  this returns eCompileNoError if */
  79. /* everything is ok, and the appropriate type in *ResultingDataType. */
  80. CompileErrors                TypeCheckFunctionCall(DataTypes* ResultingDataType,
  81.                                             ASTFuncCallRec* FunctionCall, long* ErrorLineNumber,
  82.                                             struct TrashTrackRec* TrashTracker)
  83.     {
  84.         CompileErrors            Error;
  85.         SymbolRec*                FunctionSymbol;
  86.         SymbolListRec*        FunctionArgumentStepper;
  87.         ASTExprListRec*        ExpressionListStepper;
  88.  
  89.         CheckPtrExistence(FunctionCall);
  90.         CheckPtrExistence(TrashTracker);
  91.  
  92.         /* get the symbol for the function */
  93.         Error = ExpressionGetFunctionCallSymbol(&FunctionSymbol,
  94.             FunctionCall->FunctionGenerator);
  95.         if (Error != eCompileNoError)
  96.             {
  97.                 *ErrorLineNumber = FunctionCall->LineNumber;
  98.                 return Error;
  99.             }
  100.         CheckPtrExistence(FunctionSymbol);
  101.  
  102.         FunctionArgumentStepper = GetSymbolFunctionArgList(FunctionSymbol);
  103.         ExpressionListStepper = FunctionCall->ArgumentList;
  104.         while ((FunctionArgumentStepper != NIL) && (ExpressionListStepper != NIL))
  105.             {
  106.                 DataTypes                    FormalType;
  107.                 DataTypes                    ActualType;
  108.  
  109.                 FormalType = GetSymbolVariableDataType(
  110.                     GetFirstFromSymbolList(FunctionArgumentStepper));
  111.                 Error = TypeCheckExpression(&ActualType,ExprListGetFirstExpr(
  112.                     ExpressionListStepper),ErrorLineNumber,TrashTracker);
  113.                 if (Error != eCompileNoError)
  114.                     {
  115.                         return Error;
  116.                     }
  117.                 if (!CanRightBeMadeToMatchLeft(FormalType,ActualType))
  118.                     {
  119.                         *ErrorLineNumber = FunctionCall->LineNumber;
  120.                         return eCompileArgumentTypeConflict;
  121.                     }
  122.                 if (MustRightBePromotedToLeft(FormalType,ActualType))
  123.                     {
  124.                         ASTExpressionRec*        PromotedThing;
  125.  
  126.                         /* consequent must be promoted to be same as alternate */
  127.                         PromotedThing = PromoteTheExpression(ActualType/*orig*/,
  128.                             FormalType/*desired*/,ExprListGetFirstExpr(ExpressionListStepper),
  129.                             FunctionCall->LineNumber,TrashTracker);
  130.                         if (PromotedThing == NIL)
  131.                             {
  132.                                 *ErrorLineNumber = FunctionCall->LineNumber;
  133.                                 return eCompileOutOfMemory;
  134.                             }
  135.                         ExprListPutNewFirst(ExpressionListStepper,PromotedThing);
  136.                         /* sanity check */
  137.                         Error = TypeCheckExpression(&ActualType/*obtain new type*/,
  138.                             ExprListGetFirstExpr(ExpressionListStepper),ErrorLineNumber,TrashTracker);
  139.                         ERROR(Error != eCompileNoError,PRERR(ForceAbort,
  140.                             "TypeCheckFunctionCall:  type promotion caused failure"));
  141.                         ERROR(ActualType != FormalType,PRERR(ForceAbort,
  142.                             "TypeCheckFunctionCall:  after type promotion, types are no"
  143.                             " longer the same"));
  144.                     }
  145.  
  146.                 /* advance to the next list thing */
  147.                 ExpressionListStepper = ExprListGetRestList(ExpressionListStepper);
  148.                 FunctionArgumentStepper = GetRestListFromSymbolList(FunctionArgumentStepper);
  149.             }
  150.         if ((ExpressionListStepper != NIL) || (FunctionArgumentStepper != NIL))
  151.             {
  152.                 *ErrorLineNumber = FunctionCall->LineNumber;
  153.                 return eCompileWrongNumberOfArgsToFunction;
  154.             }
  155.  
  156.         *ResultingDataType = GetSymbolFunctionReturnType(FunctionSymbol);
  157.         return eCompileNoError;
  158.     }
  159.  
  160.  
  161. /* generate code for a function call. returns True if successful, or False if it fails. */
  162. MyBoolean                        CodeGenFunctionCall(struct PcodeRec* FuncCode,
  163.                                             long* StackDepthParam, ASTFuncCallRec* FunctionCall)
  164.     {
  165.         long                            StackDepth;
  166.         SymbolRec*                FunctionSymbol;
  167.         ASTOperandRec*        FunctionContainer;
  168.         DataTypes*                DataTypeArray;
  169.         SymbolListRec*        FormalArgumentList;
  170.         long                            Index;
  171.  
  172.         CheckPtrExistence(FuncCode);
  173.         CheckPtrExistence(FunctionCall);
  174.         StackDepth = *StackDepthParam;
  175.  
  176.         /* push word for return value */
  177.         if (!AddPcodeInstruction(FuncCode,epStackAllocate,NIL))
  178.             {
  179.                 return False;
  180.             }
  181.         StackDepth += 1;
  182.  
  183.         /* push each argument on stack; from left to right */
  184.         if (!CodeGenExpressionListArguments(FuncCode,&StackDepth,FunctionCall->ArgumentList))
  185.             {
  186.                 return False;
  187.             }
  188.  
  189.         /* figure out how to call the function */
  190.         FunctionContainer = GetOperandOutOfExpression(FunctionCall->FunctionGenerator);
  191.         FunctionSymbol = GetSymbolFromOperand(FunctionContainer);
  192.         if (!AddPcodeInstruction(FuncCode,epFuncCallUnresolved,NIL))
  193.             {
  194.                 return False;
  195.             }
  196.         /* push function name */
  197.         if (!AddPcodeOperandString(FuncCode,GetSymbolName(FunctionSymbol),
  198.             PtrSize(GetSymbolName(FunctionSymbol))))
  199.             {
  200.                 return False;
  201.             }
  202.         /* push a parameter list record for runtime checking */
  203.         FormalArgumentList = GetSymbolFunctionArgList(FunctionSymbol);
  204.         /* now that we have the list, let's just check the stack for consistency */
  205.         ERROR(StackDepth != *StackDepthParam + 1 + GetSymbolListLength(FormalArgumentList),
  206.             PRERR(ForceAbort,"CodeGenFunctionCall:  stack depth error after pushing args"));
  207.         DataTypeArray = (DataTypes*)AllocPtrCanFail(sizeof(DataTypes)
  208.             * GetSymbolListLength(FormalArgumentList),"Function Parameter Type List");
  209.         if (DataTypeArray == NIL)
  210.             {
  211.                 return False;
  212.             }
  213.         Index = 0;
  214.         while (FormalArgumentList != NIL)
  215.             {
  216.                 DataTypeArray[Index] = GetSymbolVariableDataType(
  217.                     GetFirstFromSymbolList(FormalArgumentList));
  218.                 Index += 1;
  219.                 FormalArgumentList = GetRestListFromSymbolList(FormalArgumentList);
  220.             }
  221.         if (!AddPcodeOperandDataTypeArray(FuncCode,DataTypeArray))
  222.             {
  223.                 ReleasePtr((char*)DataTypeArray);
  224.                 return False;
  225.             }
  226.         ReleasePtr((char*)DataTypeArray);
  227.         /* save the return type */
  228.         if (!AddPcodeOperandInteger(FuncCode,GetSymbolFunctionReturnType(FunctionSymbol)))
  229.             {
  230.                 return False;
  231.             }
  232.         /* make an instruction operand for the "reserved" thing */
  233.         if (!AddPcodeOperandInteger(FuncCode,0))
  234.             {
  235.                 return False;
  236.             }
  237.  
  238.         /* increment stack pointer since there will be 1 returned value */
  239.         (*StackDepthParam) += 1;
  240.  
  241.         return True;
  242.     }
  243.